{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "C02. 列表和元组\n",
    "==========\n",
    "\n",
    "数据结构：以某种方式(如通过编号)组合起来的数据元素(如数、字符及至其他数据结构)集合。\n",
    "-   在Python中，最基本的数据结构为序列\n",
    "-   序列中的每个元素都有编号，即其位置 或者 索引\n",
    "    -   第一个元素的索引为0，后面依次类推\n",
    "    -   从0开始指出相对于序列开头的偏移量\n",
    "\n",
    "2.1 序列概述\n",
    "--------\n",
    "\n",
    "Python 最常用的两种序列：**列表** 和 **元组**\n",
    "\n",
    "-   列表是可以修改的\n",
    "    -   可以中途添加元素\n",
    "    -   所有元素都放在方括号内，并且用逗号分隔\n",
    "-   元组是不可以修改的\n",
    "    -   禁止中途修改元素"
   ]
  },
  {
   "cell_type": "code",
   "source": [
    "edward=['Edward Gumby',42]\n",
    "john=['John Smith',50]\n",
    "database=[edward,john]\n",
    "database"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   },
   "execution_count": 1,
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "[['Edward Gumby', 42], ['John Smith', 50]]"
      ]
     },
     "metadata": {},
     "execution_count": 1
    }
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "2.2 通用的序列操作\n",
    "--------\n",
    "\n",
    "**索引**、**切片**、**相加**、**相乘**、**成员资格检查**、确定序列的长度、找出序列中的最大或者最小元素\n",
    "\n",
    "注：**迭代** 将在 (Sec 5.5) 介绍\n",
    "\n",
    "### 2.2.1 索引\n",
    "\n",
    "索引：可以用来获取元素。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "January 1st,1919\n"
     ]
    }
   ],
   "source": [
    "# Code 2-1 : 索引操作\n",
    "# 打印以数指定的年、月、日的日期\n",
    "\n",
    "months = ['January', 'February', 'Mark', 'April', 'May', 'June', 'July', 'August', 'September',\n",
    "          'October', 'November', 'December']\n",
    "\n",
    "endings = ['st', 'nd', 'rd'] + 17 * ['th'] + ['st', 'nd', 'rd'] + 7 * ['th'] + ['st']\n",
    "year = input('Year: ')\n",
    "month = input('Month (1-12): ')\n",
    "day = input('Day (1-31): ')\n",
    "\n",
    "month_number = int(month)\n",
    "day_number = int(day)\n",
    "\n",
    "month_name = months[month_number - 1]\n",
    "ordinal = day + endings[day_number - 1]\n",
    "\n",
    "print(month_name + ' ' + ordinal + ',' + year)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.2.2 切片\n",
    "\n",
    "切片用来访问特定范围内的元素，使用两个索引，并且用冒号分隔。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Code 2-2：提取域名\n",
    "url = input('Please enter the URL: ')\n",
    "domain = url[11:-4]\n",
    "print(\"Domain name: \" + domain)\n",
    "\n",
    "# 更大的步长\n",
    "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
    "print(numbers[2:8])\n",
    "print(numbers[2:8:1])\n",
    "print(numbers[2:8:-1])\n",
    "print(numbers[8:2:-1])\n",
    "print(numbers[8:2:-2])\n",
    "print(numbers[2:8:2])\n",
    "print(numbers[::2])\n",
    "print(numbers[::-2])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.2.3 序列相加\n",
    "使用加法运算符来拼接序列"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "print([1, 2, 3] + [4, 5, 6])\n",
    "print(\"Hello,\" + \"world!\")\n",
    "print([1, 2, 3] + \"world!\") # 会报错"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.2.4 乘法\n",
    "使用乘法运算符通过重复原始序列来生成新的序列"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "print('Python!' * 5)\n",
    "print([42] * 5)\n",
    "\n",
    "# Code 2-3：屏幕中央打印句子\n",
    "\n",
    "sentence = input(\"Sentence: \")\n",
    "\n",
    "screen_width = 80\n",
    "text_width = len(sentence)\n",
    "box_width = text_width + 6\n",
    "left_margin = (screen_width - box_width) // 2\n",
    "\n",
    "print()\n",
    "print(' ' * left_margin + '+' + '-' * (box_width - 2) + '+')\n",
    "print(' ' * left_margin + '|  ' + ' ' * text_width + '  |')\n",
    "print(' ' * left_margin + '|  ' + sentence + '  |')\n",
    "print(' ' * left_margin + '|  ' + ' ' * text_width + '  |')\n",
    "print(' ' * left_margin + '+' + '-' * (box_width - 2) + '+')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.2.5 成员资格\n",
    "使用布尔运算符 in"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Code 2-4: 序列成员资格示例\n",
    "# 检查用户名和 PIN 码\n",
    "\n",
    "database=[\n",
    "        ['albert','1234'],\n",
    "        ['dilbert','4242'],\n",
    "        ['smith','7524'],\n",
    "        ['jones','9843']\n",
    "]\n",
    "\n",
    "username=input(\"User name: \")\n",
    "pin=input(\"PIN code: \")\n",
    "\n",
    "if [username,pin] in database:\n",
    "    print(\"Access granted\")\n",
    "\n",
    "numbers=[100,34,678]\n",
    "print(\"numbers length: \",len(numbers))\n",
    "print(\"max numbers: \",max(numbers))\n",
    "print(\"min numbers: \",min(numbers))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "\n",
    "2.3 列表概述\n",
    "--------\n",
    "\n",
    "### 2.3.1 List()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(\"list('Hello') =\",list('Hello'))\n",
    "print(\"['H', 'e', 'l', 'l', 'o'] = \",''.join(list('Hello')))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.3.2 列表操作"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 修改列表：给元素赋值\n",
    "x=[1,1,1]\n",
    "x[1]=2\n",
    "print(\"x=\",x)\n",
    "\n",
    "# 删除元素\n",
    "names=['Alice''Beth','Cecil','Dee-Dee','Earl']\n",
    "print(\"names =\",names)\n",
    "del names[2]\n",
    "print(\"names after del 2 =\",names)\n",
    "\n",
    "# 给切片赋值\n",
    "# 替换\n",
    "name=list('Perl')\n",
    "print(\"name =\",name)\n",
    "name[2:]=list('ar')\n",
    "print(\"name =\",name)\n",
    "# 延长\n",
    "name=list('Perl')\n",
    "print(\"name =\",name)\n",
    "name[1:]=list('ython')\n",
    "print(\"name =\",name)\n",
    "#插入\n",
    "numbers=[1,5]\n",
    "print(\"numbers =\",numbers)\n",
    "numbers[1:1]=[2,3,4]\n",
    "print(\"numbers =\",numbers)\n",
    "#空切片\n",
    "numbers[1:4]=[]\n",
    "print(\"numbers =\",numbers)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 2.3.3 列表方法\n",
    "方法是与对象(列表、数字、字符串等)联系紧密的函数"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "source": [
    "1.  append()"
   ],
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "cell_type": "code",
   "source": [
    "lst=[1,2,3]\n",
    "print(\"lst =\",lst)\n",
    "lst.append(4)\n",
    "print(\"lst =\",lst)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   },
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "source": [
    "2.  clear()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "lst.clear()\n",
    "print(\"lst =\",lst)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "3.  copy()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "a=[1,2,3]\n",
    "print(\"a=\",a)\n",
    "b=a\n",
    "b[1]=4\n",
    "print(\"a=\",a)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "4.  count()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(['我','我','你','他'].count('我'))\n",
    "print([1,1,2,3].count(2))\n",
    "print([[1,2],[1,2],[1,[1,2]]].count([1,2]))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "5.  extend()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "a=[1,2,3]\n",
    "print(\"a=\",a)\n",
    "b=[4,5,6]\n",
    "print(\"b=\",b)\n",
    "print(\"a+b=\",a+b)\n",
    "print(\"a=\",a)\n",
    "print(\"b=\",b)\n",
    "a.extend(b)\n",
    "print(\"a.extend(b)=\",a)\n",
    "print(\"b=\",b)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "6.  index()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "knights=['我','是','中','国','人']\n",
    "print(\"knights.index('我')=\",knights.index('中'))\n",
    "print(\"knights[4]=\",knights[4])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "7.  insert()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "numbers=[1,2,3,5,6,7]\n",
    "print(\"numbers = \",numbers)\n",
    "numbers.insert(3,'four')\n",
    "print(\"numbers = \",numbers)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "8.  pop()：是惟一既修改列表又返回一个非 None 值的列表方法\n",
    "    -   pop()和append()可以组成一对操作，控制后进先出(LIFO)队列\n",
    "    -   pop(0)和insert(0,...)可以组成一对操作，控制先进先出(FIFO)队列，具体参考 Ch10"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "x=[1,2,3]\n",
    "print(\"x=\",x)\n",
    "x.pop()\n",
    "print(\"x=\",x)\n",
    "x.append(4)\n",
    "print(\"x=\",x)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "9.  remove() 用于删除第一个为指定值的元素"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "x=['to','be','or','not','to','be']\n",
    "print(\"x=\",x)\n",
    "x.remove('be')\n",
    "print(\"x=\",x)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "1.  reverse() 按相反的顺序排列列表中的元素"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "x=[1,2,3]\n",
    "print(\"x=\",x)\n",
    "x.reverse()\n",
    "print(\"x=\",x)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "11.  sort() 用于对列表就地排序"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "x=[4,6,2,1,7,9]\n",
    "print(\"x=\",x)\n",
    "x.sort()\n",
    "print(\"x=\",x)\n",
    "print('-'*10)\n",
    "x=[4,6,2,1,7,9]\n",
    "print(\"x=\",x)\n",
    "y=x.sort()\n",
    "print(\"x=\",x)\n",
    "print(\"y=\",y)\n",
    "print('-'*10)\n",
    "x=[4,6,2,1,7,9]\n",
    "print(\"x=\",x)\n",
    "y=sorted(x)\n",
    "print(\"x=\",x)\n",
    "print(\"y=\",y)\n",
    "print(\"sorted('Python')=\",sorted('Python'))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "12.  高级排序：sort()可以接受两个可选参数\n",
    "    -   key：设置一个用于排序的函数，系统使用这个函数创建元素的键，再使用键进行排序\n",
    "    -   reverse：true/false 是否反序排列"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "x=['1','12','123','4','45','456','4567']\n",
    "print(\"x=\",x)\n",
    "x.sort(key=len)\n",
    "print(\"x=\",x)\n",
    "x.sort(reverse=True)\n",
    "print(\"x=\",x)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2.4 元组概述\n",
    "\n",
    "元组：是不可修改的序列\n",
    "\n",
    "-   它们用作映射中的键(以及集合的成员)，而列表不行\n",
    "-   有些内置函数和方法返回元组，\n",
    "\n",
    "注：使用列表中心满足序列操作的需要"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "x= (1, 2, 3)\n----------\nx= (42,)\n----------\n"
     ]
    }
   ],
   "source": [
    "# 元组定义\n",
    "x=(1,2,3)\n",
    "print(\"x=\",x)\n",
    "print('-'*10)\n",
    "x=(42,)\n",
    "print(\"x=\",x)\n",
    "print('-'*10)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "x= 126\n----------\nx= (42, 42, 42)\n----------\n"
     ]
    }
   ],
   "source": [
    "x=3*(40+2)\n",
    "print(\"x=\",x)\n",
    "print('-'*10)\n",
    "# 元组乘法\n",
    "x=3*(40+2,)\n",
    "print(\"x=\",x)\n",
    "print('-'*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "x= (1, 2, 3)\n----------\nx= ('a', 'b', 'c')\n----------\nx= (1, 2, 3)\n----------\n"
     ]
    }
   ],
   "source": [
    "# 元组函数 tuple()\n",
    "# 列表转成元组\n",
    "x=tuple([1,2,3])\n",
    "print(\"x=\",x)\n",
    "print('-'*10)\n",
    "# 字符串转成元组\n",
    "x=tuple('abc')\n",
    "print(\"x=\",x)\n",
    "print('-'*10)\n",
    "# 元组转成元组\n",
    "x=tuple((1,2,3))\n",
    "print(\"x=\",x)\n",
    "print('-'*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "x[1]= 2\nx[0:2]= (1, 2)\n"
     ]
    }
   ],
   "source": [
    "# 元组切片\n",
    "x=1,2,3\n",
    "print(\"x[1]=\",x[1])\n",
    "print(\"x[0:2]=\",x[0:2])"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2.5 小结\n",
    "\n",
    "-   序列：是一种数据结构，其中的元素带编号(编号从0开始)。列表、字符串和元组都属于序列。\n",
    "    -   列表是可变的\n",
    "        -   修改列表的方式就是对其元素或者切片赋值\n",
    "    -   元组和字符串是不可变的\n",
    "    -   切片可以用于访问序列中的一部分，需要提供切片起始和结束位置的索引\n",
    "-   成员资格：使用运算符 `in` 可以确定特定的值是否包含在序列(或者其他容器中)\n",
    "    -   在字符串中使用运算符 `in` 可以查找子串\n",
    "-   方法：内置的类型(例如：列表和字符串，不包括元组)提供了许多有用的方法\n",
    "    -   方法类似于函数，只与特定的值相关联\n",
    "    -   方法是面向对象编程的重要方面，参考 Ch07"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "source": [
    "### 2.5.1 本章介绍的新函数\n",
    "\n",
    "| 函数          | 描述                                           |\n",
    "| ------------- | ---------------------------------------------- |\n",
    "| len(seq)      | 返回序列的长度                                 |\n",
    "| list(seq)     | 将序列转换成列表                               |\n",
    "| max(args)     | 返回序列或者一组参数中的最大值                 |\n",
    "| min(args)     | 返回序列或者一组参数中的最小值                 |\n",
    "| reversed(seq) | 反向迭代序列                                   |\n",
    "| sorted(seq)   | 返回一个有序列表，其中包含指定序列中的所有元素 |\n",
    "| tuple(seq)    | 将序列转换成元组                               | "
   ],
   "cell_type": "markdown",
   "metadata": {}
  }
 ],
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.6.12 64-bit ('Begin': conda)",
   "metadata": {
    "interpreter": {
     "hash": "5418aa4018a4a6d4e7a95d1864632b051ddd71a0141746edebf6fac21ca2c6f9"
    }
   }
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "3.6.12-final"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "source": [],
    "metadata": {
     "collapsed": false
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}